﻿/****************************************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (http://rapidwebdev.org)
	Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@RapidWebDev.org

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************************************/

using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using BaoJianSoft.RapidWeb.Properties;
using BaoJianSoft.Common;
using System.Reflection;

namespace BaoJianSoft.RapidWeb.DynamicPages.Configurations
{
	/// <summary>
	/// Form panel will be rendered as a form to create/edit/view records or any operations for the records.
	/// </summary>
	public class FormPanelConfiguration : BasePanelConfiguration
	{
		private string typeName;
		private DynamicPagePanelTypes dynamicPagePanelType;

		/// <summary>
		/// The C# managed type of dynamic page which implements the interface IDynamicComponent (IDetailPanelPage/IAggregatePanelPage).
		/// </summary>
		public Type @Type
		{
			get
			{
				Type dynamicComponentType = Kit.GetType(this.typeName);
				if ((dynamicComponentType.GetInterface(typeof(IDetailPanelPage).FullName) != null && this.PanelType == DynamicPagePanelTypes.DetailPanel)
					|| (dynamicComponentType.GetInterface(typeof(IAggregatePanelPage).FullName) != null && this.PanelType == DynamicPagePanelTypes.AggregatePanel))
				{
					return dynamicComponentType;
				}

				throw new ConfigurationErrorsException(Resources.DP_ConfiguredFormPanelPageTypeDoesNotMatchPanelType);
			}
		}

		/// <summary>
		/// Specify an ASCX template to render panel UI. Here supports both relative(~/) and abosolute path.
		/// </summary>
		public string SkinPath { get; set; }

		/// <summary>
		/// The width of form panel (defaults to 960).
		/// </summary>
		public int Width { get; set; }

		/// <summary>
		/// The height of form panel (defaults to 600).
		/// </summary>
		public int Height { get; set; }

		/// <summary>
		/// True indicates the form panel is resizable (defaults to false).
		/// </summary>
		public bool Resizable { get; set; }

		/// <summary>
		/// True indicates the form panel is draggable (defaults to false).
		/// </summary>
		public bool Draggable { get; set; }

		/// <summary>
		/// True indicates show message box in UI after saved successfully (defaults to true).
		/// </summary>
		public bool ShowMessageAfterSavedSuccessfully { get; set; }

		/// <summary>
		/// Sets/gets FormPanelButtonConfiguration to save button of panel. The default value is null which means not to display save button.
		/// </summary>
		public FormPanelButtonConfiguration SaveButton { get; set; }

		/// <summary>
		/// Sets/gets FormPanelButtonConfiguration to cancel button of panel. The default value is null which means not to display cancel button.
		/// </summary>
		public FormPanelButtonConfiguration CancelButton { get; set; }

		/// <summary>
		/// Gets panel type - form panel. Form panel will be rendered as a form to create/edit/view records or any operations for the records.
		/// </summary>
		public override DynamicPagePanelTypes PanelType { get { return this.dynamicPagePanelType; } }

		/// <summary>
		/// Construct panel Configuration
		/// </summary>
		/// <param name="typeName">The C# managed type of dynamic page which implements the interface IDynamicComponent (IDetailPanelPage/IAggregatePanelPage).</param>
		public FormPanelConfiguration(string typeName) : base() 
		{
			Kit.NotNull(typeName, "typeName");

			this.Width = 960;
			this.Height = 600;
			this.typeName = typeName;
			this.ShowMessageAfterSavedSuccessfully = true;
			ValidateTypeName(typeName, "Manual Constructed");
		}

		/// <summary>
		/// Construct FormPanelConfiguration instance from xml element.
		/// </summary>
		/// <param name="panelElement"></param>
		/// <param name="xmlParser"></param>
		public FormPanelConfiguration(XmlElement panelElement, XmlParser xmlParser) : base(panelElement, xmlParser)
		{
			this.typeName = xmlParser.ParseString(panelElement, "p:Type");
			if (!Kit.IsEmpty(this.typeName))
			{
				string objectId = panelElement.OwnerDocument.SelectSingleNode("p:Page/@ObjectId", xmlParser.NamespaceManager).Value;
				ValidateTypeName(objectId, this.typeName);
			}
			else
			{
				// use @Type of page element if Type is not specified on the element itself.
				// don't need to validate @Type of page in this block since the validation has been done when constructing DynamicPageConfiguration.
				this.typeName = panelElement.OwnerDocument.SelectSingleNode("p:Page/@Type", xmlParser.NamespaceManager).Value;
			}

			this.SkinPath = xmlParser.ParseString(panelElement, "p:SkinPath");
			this.Width = xmlParser.ParseInt(panelElement, "@Width", 960);
			this.Height = xmlParser.ParseInt(panelElement, "@Height", 600);
			this.Resizable = xmlParser.ParseBoolean(panelElement, "@Resizable", false);
			this.Draggable = xmlParser.ParseBoolean(panelElement, "@Draggable", false);
			this.ShowMessageAfterSavedSuccessfully = xmlParser.ParseBoolean(panelElement, "@ShowMessageAfterSavedSuccessfully", true);

			XmlElement saveButtonElement = panelElement.SelectSingleNode("p:SaveButton", xmlParser.NamespaceManager) as XmlElement;
			if (saveButtonElement != null)
			{
				this.SaveButton = new FormPanelButtonConfiguration(saveButtonElement, xmlParser);
				this.SaveButton.Text = this.SaveButton.Text ?? Resources.DPCtrl_SaveText;
			}

			XmlElement cancelButtonElement = panelElement.SelectSingleNode("p:CancelButton", xmlParser.NamespaceManager) as XmlElement;
			if (cancelButtonElement != null)
			{
				this.CancelButton = new FormPanelButtonConfiguration(cancelButtonElement, xmlParser);
				this.CancelButton.Text = this.CancelButton.Text ?? Resources.DPCtrl_CancelText;
			}
		}

		/// <summary>
		/// Set panel type.
		/// </summary>
		/// <param name="panelType"></param>
		internal void SetPanelType(DynamicPagePanelTypes panelType)
		{
			this.dynamicPagePanelType = panelType;
		}

		private static void ValidateTypeName(string objectId, string typeName)
		{
			Type type = Kit.GetType(typeName);
			if (type != null)
			{
				ConstructorInfo typeConstructor = type.GetConstructor(Type.EmptyTypes);
				if (!(typeConstructor.Invoke(null) is IDynamicComponent))
					throw new ConfigurationErrorsException(string.Format(Resources.DP_ConfiguredFormPanelTypeNotImplementIDynamicComponent, typeName, objectId));
			}
			else
				throw new ConfigurationErrorsException(string.Format(Resources.DP_ConfiguredFormPanelTypeNotExists, typeName, objectId));
		}
	}

	/// <summary>
	/// Form panel button will be rendered as a common style button in the form.
	/// </summary>
	public class FormPanelButtonConfiguration
	{
		private string text;
		private string tooltip;

		/// <summary>
		/// Sets/gets generic button display text.
		/// </summary>
		public string Text
		{
			set { this.text = value; }
			get { return WebUtility.ReplaceVariables(this.text); }
		}

		/// <summary>
		/// Sets/gets generic button tooltip.
		/// </summary>
		public string ToolTip
		{
			set { this.tooltip = value; }
			get { return WebUtility.ReplaceVariables(this.tooltip); }
		}

		/// <summary>
		/// Construct FormPanelButtonConfiguration instance from xml element.
		/// </summary>
		/// <param name="buttonElement"></param>
		/// <param name="xmlParser"></param>
		public FormPanelButtonConfiguration(XmlElement buttonElement, XmlParser xmlParser)
		{
			this.Text = xmlParser.ParseString(buttonElement, "@Text");
			this.ToolTip = xmlParser.ParseString(buttonElement, "@ToolTip");
		}
	}
}
